package com.example.a10928.weifriend.http.poll;


import com.example.a10928.weifriend.App;

import java.util.HashMap;
import java.util.Map;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Predicate;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.BehaviorSubject;

import static com.example.a10928.weifriend.http.poll.EventInterface.BizEvent.ALL;


/**
 * Created by Chuang on 2018/4/4.
 * 因为以前的那个轮询太弱智了,所以花时间重新写了个,支持绑定Activity和Fragment的生命周期
 * 还可以自由控制start与stop {@link}有事例
 */
public class PollingManager {


    private HashMap<String, SubjectModel<EventInterface>> activeSubjectMap;
    private BehaviorSubject<EventInterface> subject;


    private PollingManager() {
        activeSubjectMap = new HashMap<>();
    }

    public static PollingManager getInstance() {
        if (null == App.manager) {
            synchronized (PollingManager.class) {
                if (null ==  App.manager) {
                    App.manager = new PollingManager();
                }
            }
        }

        return  App.manager;
    }

    private void clearSubject(String tag) {
        activeSubjectMap.get(tag).clearSubject();
    }

    private BehaviorSubject<EventInterface> getSubject(String tag) {
        return subject;
    }
    private void createSubject(IntervalPolling intervalPolling) {
        subject = BehaviorSubject.create();
        Disposable execute = intervalPolling.execute(PollingManager.getInstance());
//        this.activeSubjectMap.put(subject.getValue(),new SubjectModel<EventInterface>(
//                intervalPolling.execute(new PollingManager()),intervalPolling,subject))
        activeSubjectMap.put(intervalPolling.tag,new SubjectModel<EventInterface>(execute,intervalPolling, subject));
    }

    private void startPolling(String tag) {
        getSubject(tag).onSubscribe(activeSubjectMap.get(tag).getDisposable());
    }

    public boolean stopPolling(String tag, EventInterface event) {
        BehaviorSubject<EventInterface> subject = getSubject(tag);
        if (null == subject) {
//            Timber.tag(Constants.TAG).e("can not find subject according to the %s", tag);
            return false;
        }

        subject.onNext(event);
//        Timber.tag(Constants.TAG).i("Stop Polling SubjectTag =  " + tag + ", Event = " + event.toString());

        return true;
    }

    public void emitEvent( @NonNull EventInterface event){
        if (null == activeSubjectMap) return;

        for (Map.Entry<String, SubjectModel<EventInterface>> next : activeSubjectMap.entrySet()) {
            BehaviorSubject<EventInterface> behaviorSubject = next.getValue().getBehaviorSubject();
            if (null == behaviorSubject) return;
            behaviorSubject.onNext(event);
        }
    }


    public BehaviorSubject<EventInterface> bindIntervalEvent(
            int interval, @NonNull String tag, @NonNull EventInterface eventInterface, PollingRequest.PollingAction action){

//        if(activeSubjectMap != null){
//            for (Map.Entry<String, SubjectModel<EventInterface>> stringSubjectModelEntry : activeSubjectMap.entrySet()) {
//                if (stringSubjectModelEntry.getKey().equals(tag)) {
//                    startPolling(tag);
//                    return activeSubjectMap.get(tag).getBehaviorSubject();
//                }else{
//                    //1.创建轮询器
                    IntervalPolling intervalPolling = new IntervalPolling(interval, tag, eventInterface, action);
//
//                    //2.创建Subject
                    createSubject(intervalPolling);
//                }
//            }
//        }


        //3.启动轮询
        startPolling(tag);

        //4.返回Subject
        return activeSubjectMap.get(tag).getBehaviorSubject();
    }




    public ObservableTransformer<Long, Long> composeEvent(final String tag, final EventInterface outEvent) {

        BehaviorSubject<EventInterface> subject = getSubject(tag);
        if (null == subject) {
//      Timber.tag(Constants.TAG).e("subject = null");
            return new EmptyObservableTransformer();
        }

        final Observable<EventInterface> observable = subject.filter(new Predicate<EventInterface>() {
            @Override
            public boolean test(EventInterface event) {
//        Timber.tag(Constants.TAG).i("receive event: %s", event);
                boolean filter = outEvent == event || event == ALL;
                if (filter) clearSubject(tag);
                return filter;
            }
        });

        return new ObservableTransformer<Long, Long>() {
            @Override
            public ObservableSource<Long> apply(Observable<Long> upstream) {
                return upstream.subscribeOn(Schedulers.io()).takeUntil(observable);
            }
        };
    }


}
